package com.weiling.util;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class VideoConverterUtil {

    /**
     * 是执行 FFmpeg 命令行，并将 FFmpeg 的输出转换为字符串形式返回。
     *
     * @param cmd     表示要执行的 FFmpeg 命令行。
     * @param isInput 用于指示是否需要获取 FFmpeg 的输入流。如果为 true，则获取 FFmpeg 的输入流；如果为 false，则获取 FFmpeg 的错误流。
     * @return 表示执行 FFmpeg 命令行的输出结果，以字符串形式返回。如果执行命令出现异常，则返回 null。
     */
    private static String executeFFmpegCmd(String[] cmd, boolean isInput) {
        StringBuilder output = new StringBuilder();
        try {
            Process process = Runtime.getRuntime().exec(cmd);
            InputStream inputStream = isInput ? process.getInputStream() : process.getErrorStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
                System.out.println(line);
            }
            process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return null;
        }
        return output.toString();
    }

    /**
     * 根据输入路径和输出后缀名生成输出路径。
     *
     * @param inputPath       输入路径，即待转换的文件路径
     * @param outputExtension 表示输出文件的后缀名
     * @return 生成的输出文件路径，包括完整的文件名和路径。
     */
    private static String generateOutputFilePath(String inputPath, String outputExtension) {
        String dirPath = FilenameUtils.getFullPath(inputPath);
        String baseName = FilenameUtils.getBaseName(inputPath);
        return dirPath + baseName + outputExtension;
    }

    /**
     * 将指定路径的mp4格式视频转为webm格式
     *
     * @param mp4Path mp4格式视频文件路径
     * @return 生成的webm格式视频文件路径
     */
    public static String mp4ToWebm(String mp4Path) {
        String webmPath = generateOutputFilePath(mp4Path, ".webm");
        String[] ffmpegCmd = {"ffmpeg", "-i", mp4Path, "-c:v", "libvpx-vp9", "-crf", "30", "-b:v", "0", "-b:a", "128k", "-deadline", "realtime", "-cpu-used", "4", webmPath};
        if (executeFFmpegCmd(ffmpegCmd, false) != null) {
            return webmPath;
        } else {
            return null;
        }
    }

    /**
     * 将指定的mp4格式视频二进制数据转为webm格式
     *
     * @param mp4Data mp4格式视频的二进制数据
     * @return 生成的webm格式视频的二进制数据
     */
    public static byte[] mp4DataToWebmData(byte[] mp4Data) {
        try {
            // 将mp4格式视频写入临时文件
            File tempFile = File.createTempFile("temp", ".mp4");
            tempFile.deleteOnExit();
            FileUtils.writeByteArrayToFile(tempFile, mp4Data);

            // 调用mp4ToWebm方法将临时文件转为webm格式
            String webmPath = mp4ToWebm(tempFile.getAbsolutePath());

            // 读取webm格式视频的数据
            byte[] webmData = null;
            if (webmPath != null) {
                webmData = FileUtils.readFileToByteArray(new File(webmPath));
                new File(webmPath).delete();
            }
            return webmData;

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将指定路径的webm格式视频转为mp4格式
     *
     * @param webmPath webm格式视频文件路径
     * @return 生成的mp4格式视频文件路径
     */
    public static String webmToMp4(String webmPath) {
        String mp4Path = generateOutputFilePath(webmPath, ".mp4");
        String[] ffmpegCmd = {"ffmpeg", "-i", webmPath, "-c:v", "libx264", "-crf", "23", "-preset", "medium", "-c:a", "aac", "-b:a", "128k", mp4Path};
        if (executeFFmpegCmd(ffmpegCmd, false) != null){
            return mp4Path;
        }else {
            return null;
        }

    }

    /**
     * 将指定的webm格式视频二进制数据转为mp4格式
     *
     * @param webmData webm格式视频的二进制数据
     * @return 生成的mp4格式视频的二进制数据
     */
    public static byte[] webmDataToMp4Data(byte[] webmData) {
        try {
            // 将webm格式视频写入临时文件
            File tempFile = File.createTempFile("temp", ".webm");
            tempFile.deleteOnExit();
            FileUtils.writeByteArrayToFile(tempFile, webmData);

            // 调用webmToMp4方法将临时文件转为mp4格式
            String mp4Path = webmToMp4(tempFile.getAbsolutePath());

            // 读取mp4格式视频的数据
            byte[] mp4Data = null;
            if (mp4Path != null) {
                mp4Data = FileUtils.readFileToByteArray(new File(mp4Path));
                new File(mp4Path).delete();
            }
            return mp4Data;

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}